# -*- coding: utf-8 -*-
# @File: backend => jwt.py
# @CreateTime: 2025/8/26 10:45
# @Author: EvanZhang
# @Info: JWT令牌鉴权
from typing import Optional

import jwt
from datetime import datetime, timedelta, UTC
from fastapi import HTTPException, Header
from jwt.exceptions import (
    InvalidTokenError,
    DecodeError,
    InvalidSignatureError,
    ExpiredSignatureError,
    InvalidAudienceError,
    InvalidIssuerError,
    InvalidKeyError,
    InvalidAlgorithmError,
    MissingRequiredClaimError
)

from apps.models import User

SECRET_KEY = '2656e1ac397133c36f6dbdb7ac4809c4e50b087f2f5e8baf5e01f897ab6b88ec'
ALGORITHM = 'HS256'
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_jwt_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.now(UTC) + expires_delta
    else:
        expire = datetime.now(UTC) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

async def verify_jwt_token(token: Optional[str] = Header("")):
    """
    验证token
    :param token:
    :return: 返回用户信息
    """
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=ALGORITHM)
        username: str = payload.get("sub")
        # 通过解析得到的username,并查询数据库获取用户信息
        user = await User.get_or_none(username=username)
        return user

    except ExpiredSignatureError:
        raise HTTPException(
            status_code=401,
            detail={
                'message': "Token已过期,请重新登录",
                'data': None,
            }
        )
    except (InvalidTokenError, DecodeError, InvalidSignatureError, InvalidAudienceError,
            InvalidIssuerError, InvalidKeyError, InvalidAlgorithmError, MissingRequiredClaimError) as e:
        raise HTTPException(
            status_code=401,
            detail={
                'message': "无效的Token",
                'data': str(e),
            }
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail={
                'message': "Token验证出现问题,请联系管理员",
                'data': str(e),
            }
        )


